package slap.berkeleydb;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import slap.Resources;
import slap.Slap;
import slap.paradigm.Function;

import jodd.util.Mutex;

import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.SequenceConfig;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.StoreConfig;
import com.sleepycat.persist.model.Entity;


public class BDB {
	
	private Environment env;
	private EnvironmentConfig envConfig;
	private StoreConfig storeConfig;
	private EntityStore store;
	
	private static Map<String, BDB> instanses = new HashMap<String,BDB>();
	
	public static BDB instanse(String name){
		BDB instanse = instanses.get(name);
		if(instanse == null){
			instanse = new BDB(name);
			instanses.put(name, instanse);
		}
		return instanse;
	}
	
	public BDB(String name){
		envConfig = new EnvironmentConfig();
		envConfig.setAllowCreate(true);
		env = new Environment(new File(Resources.Presets.DIR_HOME+"bdb-envs/"+name), envConfig);
		storeConfig = new StoreConfig();
		storeConfig.setAllowCreate(true);
		storeConfig.setDeferredWrite(false);
		store = new EntityStore(env, name, storeConfig);
		
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){
			@Override
			public void run() {
				shutdown();
			}
		}));
		
	}
	
	public void shutdown() {
		store.close();
		env.close();
	}

	public EntityStore getEntityStore() {
		return store;
	}
	
	public static <T> void traverse(EntityCursor<T> cursor, Function<Void, T> func){
		T entity;
		try{
			for(;(entity=cursor.next())!=null;){
				func.invoke(entity);
			}
		}finally{
			cursor.close();
		}
		
	}

	public static <I, T> List<T> asList(PrimaryIndex<I, T> primaryIndex) {
		EntityCursor<T> cursor = primaryIndex.entities();
		List<T> list = new ArrayList<T>();
		try{
			for(T enity : cursor){
				list.add(enity);
			}
		}finally{
			cursor.close();
		}
		
		return list;
	}

}
